package com.cctc.rds.scheduler.core.task;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * 任务日志。
 * 1. 任务调度器使用方提供任务类型或任务实例，并将其放入到任务实例工厂内，然后指定任务延迟执行周期，提交任务实例。
 * 2. 任务实例将以任务日志的形式进行（Raft 集群方式）存储；延迟调度服务端会使用时间轮算法自动将到期执行的任务（任务到期执行时间
 * [deadline] = 任务（重新）调度时间 + 任务延迟执行时间）放入到执行容器内；
 * 3. 任务参数实例将被序列化保存在任务日志中，以便延迟调度客户端在拉取到期执行的任务实例时进行反序列化，根据任务参数实例自动执行任务。
 * 4. 任务调度器使用方还可以随时取消已提交的任务实例，任务调度器将自动取消调度和执行被取消的任务实例。
 * 此外，对于 Raft 集群：
 * - 当 Leader 节点挂掉时，对于已经提交到任务调度器服务端的任务，或者没有任务调度器客户端拉取，或者已经被任务调度器客户端拉取
 * 但未提交执行结果的任务，都会被新的 Leader 节点锁定一段时间，然后重置为 pending 状态，重新调度，延迟执行。因此，任务调度器使用方
 * 需要自行确保任务实例的幂等执行。
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TaskLog {
    // 任务标识，由延迟调度服务端（使用雪花算法）随机生成，全局唯一。
    private long taskId;
    // 任务名称，由延迟调度器使用者提供，需保证全局唯一性。
    private String taskName;
    // 任务参数实例，序列化保存在任务日志中，以便延迟调度客户端在拉取到期执行的任务时进行反序列化，根据任务参数实例消费任务。
    private String taskParam;
    // 任务调度时间，默认为当前时间，立即调度，单位秒。
    private long scheduleTime;
    // 任务重新调度时间，默认为当前时间，立即重新调度，单位秒。
    private long retryScheduleTime;
    // 任务执行周期，如果以 0 开头，表示立即执行。
    private List<Long> execPriod;
    // 任务执行周期索引，默认从开头索引对应的延迟执行时间计算到期执行时间（[重新] 调度时间 + 执行时间），任务执行失败后自增，实现重复调度。
    private int execPriodIndex = 0;
    // 任务状态：悬决（待调度）、取消、调度中、到期（消费）执行成功、到期（消费）执行失败。
    private String status;
}
